#
#  Copyright (c) 2017, The OpenThread Authors.
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#  3. Neither the name of the copyright holder nor the
#     names of its contributors may be used to endorse or promote products
#     derived from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#  POSSIBILITY OF SUCH DAMAGE.
#

.NOTPARALLEL:

AR                              = arc-elf32-ar
CCAS                            = arc-elf32-gcc
CPP                             = arc-elf32-cpp
CC                              = arc-elf32-gcc
CXX                             = arc-elf32-g++
LD                              = arc-elf32-gcc
STRIP                           = arc-elf32-strip
NM                              = arc-elf32-nm
RANLIB                          = arc-elf32-ranlib
OBJCOPY                         = arc-elf32-objcopy

BuildJobs                      ?= 10

configure_OPTIONS               = \
    --enable-cli-app=all          \
    --enable-ncp-app=all          \
    --with-ncp-bus=uart           \
    --with-examples=emsk          \
    --enable-linker-map           \
    $(NULL)

TopSourceDir                    := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST))))..
AbsTopSourceDir                 := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))..

CONFIG_FILE                      = OPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-emsk-config.h\"'
CONFIG_FILE_PATH                 = $(AbsTopSourceDir)/examples/platforms/emsk/

COMMONCFLAGS                   := \
    -fdata-sections               \
    -ffunction-sections           \
    -Os                           \
    -g                            \
    -D$(CONFIG_FILE)              \
    -I$(CONFIG_FILE_PATH)         \
    $(NULL)

include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk

CPPFLAGS                       += \
    $(COMMONCFLAGS)               \
    $(target_CPPFLAGS)            \
    $(NULL)

CFLAGS                         += \
    $(COMMONCFLAGS)               \
    $(target_CFLAGS)              \
    $(NULL)

CXXFLAGS                       += \
    $(COMMONCFLAGS)               \
    $(target_CXXFLAGS)            \
    -fno-exceptions               \
    -fno-rtti                     \
    $(NULL)

CCASFLAGS                      += \
    $(COMMONCCASFLAGS)            \
    $(target_CCASFLAGS)           \
    $(NULL)

LDFLAGS                        += \
    $(COMMONCFLAGS)               \
    $(target_LDFLAGS)             \
    -nostartfiles                 \
    -specs=nano.specs             \
    -Wl,--gc-sections             \
    -Wl,--defsym=_STACKSIZE=524288 \
    -Wl,--defsym=_HEAPSIZE=524288 \
    $(NULL)

ECHO                            := @echo
MAKE                            := make
MKDIR_P                         := mkdir -p
LN_S                            := ln -s
RM_F                            := rm -f

INSTALL                         := /usr/bin/install
INSTALLFLAGS                    := -p

BuildPath                       = build
TopBuildDir                     = $(BuildPath)
AbsTopBuildDir                  = $(PWD)/$(TopBuildDir)

ResultPath                      = output
TopResultDir                    = $(ResultPath)
AbsTopResultDir                 = $(PWD)/$(TopResultDir)

TargetTuple                     = emsk

ARCHS                           = arcem11d

TopTargetLibDir                 = $(TopResultDir)/$(TargetTuple)/lib

ifndef BuildJobs
BuildJobs := $(shell getconf _NPROCESSORS_ONLN)
endif
JOBSFLAG := -j$(BuildJobs)

#
# configure-arch <arch>
#
# Configure OpenThread for the specified architecture.
#
#   arch - The architecture to configure.
#
define configure-arch
$(ECHO) "  CONFIG   $(TargetTuple)..."
(cd $(BuildPath)/$(TargetTuple) && $(AbsTopSourceDir)/configure \
INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
CPP="$(CPP)" CC="$(CC)" CXX="$(CXX)" CCAS="$(CCAS)" OBJC="$(OBJC)" OBJCXX="$(OBJCXX)" AR="$(AR)" RANLIB="$(RANLIB)" NM="$(NM)" STRIP="$(STRIP)" CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CCASFLAGS="$(CCASFLAGS)" LDFLAGS="$(LDFLAGS)" \
--host=arc-elf32 \
--prefix=/ \
--exec-prefix=/$(TargetTuple) \
$(configure_OPTIONS))
endef # configure-arch

#
# build-arch <arch>
#
# Build the OpenThread intermediate build products for the specified
# architecture.
#
#   arch - The architecture to build.
#
define build-arch
$(ECHO) "  BUILD    $(TargetTuple)"
$(MAKE) $(JOBSFLAG) -C $(BuildPath)/$(TargetTuple) --no-print-directory \
all
endef # build-arch

#
# stage-arch <arch>
#
# Stage (install) the OpenThread final build products for the specified
# architecture.
#
#   arch - The architecture to stage.
#
define stage-arch
$(ECHO) "  STAGE    $(TargetTuple)"
$(MAKE) $(JOBSFLAG) -C $(BuildPath)/$(TargetTuple) --no-print-directory \
DESTDIR=$(AbsTopResultDir) \
install
endef # stage-arch

#
# ARCH_template <arch>
#
# Define macros, targets and rules to configure, build, and stage the
# OpenThread for a single architecture.
#
#   arch - The architecture to instantiate the template for.
#
define ARCH_template
CONFIGURE_TARGETS += configure-$(1)
BUILD_TARGETS     += do-build-$(1)
STAGE_TARGETS     += stage-$(1)
BUILD_DIRS        += $(BuildPath)/$(TargetTuple)
DIRECTORIES       += $(BuildPath)/$(TargetTuple)

configure-$(1): target_CPPFLAGS=$($(1)_target_CPPFLAGS)
configure-$(1): target_CFLAGS=$($(1)_target_CFLAGS)
configure-$(1): target_CXXFLAGS=$($(1)_target_CXXFLAGS)
configure-$(1): target_LDFLAGS=$($(1)_target_LDFLAGS)
configure-$(1): target_CCASFLAGS=$($(1)_target_CCASFLAGS)

configure-$(1): $(BuildPath)/$(TargetTuple)/config.status

$(BuildPath)/$(TargetTuple)/config.status: | $(BuildPath)/$(TargetTuple)
	$$(call configure-arch,$(1))

do-build-$(1): configure-$(1)

do-build-$(1):
	+$$(call build-arch,$(1))

stage-$(1): do-build-$(1)

stage-$(1): | $(TopResultDir)
	$$(call stage-arch,$(1))

$(1): stage-$(1)
endef # ARCH_template

.DEFAULT_GOAL := all

all: stage

#
# EMSK2.3 arcem11d
#

# Common options
MKDEP_OPT                             = -MMD -MT $@ -MF $@.d
OPT_OLEVEL                            = -O0

# Include EMSK BSP folder
ALL_INCLUDES                          = -I$(top_srcdir)/third_party/synopsys/embarc_emsk_bsp \
                                        -I$(top_srcdir)/examples/platforms/emsk \
                                        -I$(top_srcdir)/third_party/synopsys/embarc_emsk_bsp/library/clib

# COMMON_COMPILE_OPT                  = -mno-sdata $(OPT_OLEVEL) \
                                        $(ALL_INCLUDES) $(MKDEP_OPT)

# Core options of arcem11d in EMSK2.3 from ARC TCF file
COMMON_CORE_OPT_GNU                   = -mcpu=em4_fpuda \
                                        -mlittle-endian \
                                        -mcode-density \
                                        -mdiv-rem \
                                        -mswap \
                                        -mnorm \
                                        -mmpy-option=6 \
                                        -mbarrel-shifter \
                                        -mfpu=fpuda_all \
                                        --param l1-cache-size=16384 \
                                        --param l1-cache-line-size=32

CCORE_OPT_GNU                        += $(COMMON_CORE_OPT_GNU)
CXXCORE_OPT_GNU                      += $(COMMON_CORE_OPT_GNU)
ACORE_OPT_GNU                        += $(COMMON_CORE_OPT_GNU)
LCORE_OPT_GNU                        += $(COMMON_CORE_OPT_GNU)

# C/CPP/ASM/Linker Options
COMPILE_OPT                          += $(CCORE_OPT_GNU) \
                                        $(COMMON_COMPILE_OPT) -std=gnu99
CXX_COMPILE_OPT                      += $(CXXCORE_OPT_GNU) \
                                        $(COMMON_COMPILE_OPT)
ASM_OPT                              += $(ACORE_OPT_GNU) \
                                        $(COMMON_COMPILE_OPT) -x assembler-with-cpp
LINK_OPT                             += $(LCORE_OPT_GNU) \
                                        -mno-sdata -nostartfiles --verbose

arcem11d_target_ABI                   = arcem11d
arcem11d_target_CPPFLAGS              = $(CXX_COMPILE_OPT)
arcem11d_target_CFLAGS                = $(COMPILE_OPT)
arcem11d_target_CXXFLAGS              = $(CXX_COMPILE_OPT)
arcem11d_target_CCASFLAGS             = $(ASM_OPT)
arcem11d_target_LDFLAGS               = $(LINK_OPT)

# Instantiate an architecture-specific build template for each target
# architecture.

$(foreach arch,$(ARCHS),$(eval $(call ARCH_template,$(arch))))

#
# Common / Finalization
#

configure: $(CONFIGURE_TARGETS)

build: $(BUILD_TARGETS)

stage: $(STAGE_TARGETS)

DIRECTORIES     = $(TopResultDir) $(TopResultDir)/$(TargetTuple)/lib $(BUILD_DIRS)

CLEAN_DIRS      = $(TopResultDir) $(BUILD_DIRS)

all: stage

$(DIRECTORIES):
	$(ECHO) "  MKDIR    $@"
	@$(MKDIR_P) "$@"

clean:
	$(ECHO) "  CLEAN"
	@$(RM_F) -r $(CLEAN_DIRS)

help:
	$(ECHO) "Simply type 'make -f $(firstword $(MAKEFILE_LIST))' to build OpenThread for the following "
	$(ECHO) "architectures: "
	$(ECHO) ""
	$(ECHO) "    $(ARCHS)"
	$(ECHO) ""
	$(ECHO) "To build only a particular architecture, specify: "
	$(ECHO) ""
	$(ECHO) "    make -f $(firstword $(MAKEFILE_LIST)) <architecture>"
	$(ECHO) ""
